package com.logos.ruralrevitalization.repository;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.logos.ruralrevitalization.constant.RedisConstant;
import com.logos.ruralrevitalization.entity.Msg;
import com.logos.ruralrevitalization.utils.RuralLoginUtil;
import com.logos.ruralrevitalization.utils.TouristLoginUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.logos.ruralrevitalization.constant.RedisConstant.RURAL_PREFIX;
import static com.logos.ruralrevitalization.constant.RedisConstant.USER_PREFIX;


@Component
@RequiredArgsConstructor
public class RedisChatMemory implements ChatMemory {

    private final StringRedisTemplate redisTemplate;

    private final ObjectMapper objectMapper;

    @Resource
    private TouristLoginUtil touristLoginUtil;

    @Resource
    private RuralLoginUtil ruralLoginUtil;

    @Override
    public void add(String conversationId, List<Message> messages) {
        if (messages == null || messages.isEmpty()) {
            return;
        }

        String userId = getUserId();
        List<String> list = messages.stream().map(Msg::new).map(msg -> {
            try {
                return objectMapper.writeValueAsString(msg);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }).toList();
        if (isUser()) {
            redisTemplate.opsForList().leftPushAll(USER_PREFIX + userId + ":" + conversationId, list);
        }else{
            redisTemplate.opsForList().leftPushAll(RURAL_PREFIX + userId + ":" + conversationId, list);
        }
    }

    @Override
    public List<Message> get(String conversationId, int lastN) {
        String userId = getUserId();
        List<String> list = null;
        if (isUser()) {
           list = redisTemplate.opsForList().range(USER_PREFIX + userId+ ":" + conversationId, 0, lastN);
        }else{
            list = redisTemplate.opsForList().range( RURAL_PREFIX+ userId+ ":" + conversationId, 0, lastN);
        }
        if (list == null || list.isEmpty()) {
            return List.of();
        }
        List<Message> messages = list.stream().map(s -> {
            try {
                return objectMapper.readValue(s, Msg.class);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }).map(Msg::toMessage).toList();
        List<Message> result = new ArrayList<>(messages);
        Collections.reverse(result);
        return result;
    }

    @Override
    public void clear(String conversationId) {
        String userId = getUserId();
        if (isUser()) {
            redisTemplate.delete(USER_PREFIX + userId + ":" + conversationId);
        }else{
            redisTemplate.delete(RURAL_PREFIX + userId + ":" + conversationId);
        }
    }

    private String getUserId() {
        String userId = touristLoginUtil.getId();
        if (StringUtils.isBlank(userId)) {
            userId = ruralLoginUtil.getId();
        }
        return userId;
    }

    private Boolean isUser(){
        return touristLoginUtil.getType() == 1;
    }
}